
struct Range {
    begin: i32,
    end: i32,
}

impl Range {
    fn fully_contain(&self, other: &Range) -> bool {
        self.begin <= other.begin && self.end >= other.end
    }

    fn overlap(&self, other: &Range) -> bool {
        !(self.begin > other.end || self.end < other.begin)
    }
}

impl From<&str> for Range {
    fn from(value: &str) -> Self {
        // "8-13"
        let mut iter = value.split("-").into_iter();
        let begin = iter.next().unwrap();
        let end = iter.next().unwrap();
        Range {
            begin: begin.parse().unwrap(),
            end: end.parse().unwrap(),
        }
    }
}

fn parse_input() -> Vec<(Range, Range)> {
    let input = include_str!("../input.txt");
    input
        .lines()
        .map(|line| -> (Range, Range) {
            // "8-13,10-65"
            let mut iter = line.split(",").into_iter();
            let token1 = iter.next().unwrap();
            let token2 = iter.next().unwrap();
            (token1.into(), token2.into())
        })
        .collect()
}

#[allow(unused)]
fn part1() {
    let range_pairs = parse_input();
    let count = range_pairs
        .into_iter()
        .filter(|(range1, range2)| -> bool {
            range1.fully_contain(range2) || range2.fully_contain(range1)
        })
        .count();

    println!("Part 1: {}", count);
}

#[allow(unused)]
fn part2() {
    let range_pairs = parse_input();
    let count = range_pairs
        .into_iter()
        .filter(|(range1, range2)| -> bool {
            Range::overlap(range1, range2)
        })
        .count();

    println!("Part 1: {}", count);
}

fn main() {
    part1();
    part2()
}
